package com.wunong.smart.commission.domain.service.impl;

import com.google.common.base.Preconditions;
import com.wunong.smart.commission.application.request.BaseCommissionRequest;
import com.wunong.smart.commission.application.request.support.CancelCommissionRequest;
import com.wunong.smart.commission.application.request.support.CreateCommissionRequest;
import com.wunong.smart.commission.application.request.support.FinishCommissionRequest;
import com.wunong.smart.commission.domain.business.CreateCommissionBusinessExt;
import com.wunong.smart.commission.domain.model.CommissionDomain;
import com.wunong.smart.commission.domain.repository.CommissionRepository;
import com.wunong.smart.commission.domain.service.CommissionDomainService;
import com.wunong.smart.commission.domain.state.CommissionStateFactory;
import com.wunong.smart.domain.component.lock.DistributeLockSupport;
import com.wunong.smart.domain.platform.common.BizSource;
import com.wunong.smart.domain.platform.exception.IllegalOperateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author create by zealot.zt
 */
@Slf4j
@Component
public class CommissionDomainServiceImpl implements CommissionDomainService {

    @Resource
    private DistributeLockSupport distributeLockSupport;

    @Resource
    private CommissionRepository commissionRepository;

    @Resource
    private CreateCommissionBusinessExt createCommissionBusinessExt;

    @Override
    public Long create(CreateCommissionRequest request) {
        String uniqueKey = createCommissionBusinessExt.getUniqueKey(request);

        return distributeLockSupport.withLock(() -> {
            BizSource source = request.getSource();

            CommissionDomain domain = commissionRepository.getByBiz(source, request.getCommissionType());
            if (Objects.nonNull(domain) && domain.isActive()) {
                log.info("commission#create already exist, userId:{}, id:{}", domain.getUserId(), domain.getId());
                return domain.getId();
            } else {
                domain = CommissionDomain.ofInitial();
            }

            return CommissionStateFactory.getState(domain.getStatusEnum())
                    .create(request, domain).getId();
        }, "create_commission_" + uniqueKey);
    }

    @Override
    public Void cancel(CancelCommissionRequest request) {
        return distributeLockSupport.withLock(() -> {
            CommissionDomain domain = loadCommissionDomainNonNull(request);
            CommissionStateFactory.getState(domain.getStatusEnum())
                    .cancel(request, domain);
            return null;
        }, getUniqueKey(request));
    }

    /**
     * 查询代办信息
     *
     * @param request
     * @return
     */
    protected CommissionDomain loadCommissionDomain(BaseCommissionRequest request) {
        if (Objects.isNull(request.getCommissionId())) {
            throw new IllegalOperateException("非法的代办编号");
        }

        if (Objects.nonNull(request.getUserId())) {
            return commissionRepository.getById(request.getUserId(), request.getCommissionId());
        }

        return commissionRepository.getById(request.getCommissionId());
    }

    protected CommissionDomain loadCommissionDomainNonNull(BaseCommissionRequest request) {
        CommissionDomain domain = loadCommissionDomain(request);
        Preconditions.checkArgument(domain != null, "亲，未查询到代办信息");
        return domain;
    }

    @Override
    public Void finish(FinishCommissionRequest request) {
        return distributeLockSupport.withLock(() -> {
            CommissionDomain domain = loadCommissionDomainNonNull(request);

            CommissionStateFactory.getState(domain.getStatusEnum())
                    .finish(request, domain);
            return null;
        }, getUniqueKey(request));
    }

    protected String getUniqueKey(BaseCommissionRequest request) {
        return "op_commission_" + request.getCommissionId();
    }

}
